#include <stdio.h>
#include "app.h"
#include "user_rmt.h"
#include "freertos/queue.h"


extern tSys_Flag Sys_Flag;
extern tSys_Status Sys_Status;

static const char *TAG = "IR_RECEIVER";

static QueueHandle_t ir_data_queue = NULL;
extern SemaphoreHandle_t sem_Key_Value;
static RingbufHandle_t rb = NULL;

// RMT接收配置
static rmt_config_t rmt_rx_config = {
    .channel = RMT_RX_CHANNEL,
    .gpio_num = IR_RX_GPIO_NUM,
    .clk_div = 80,  // 1MHz时钟 (80MHz/80)
    .mem_block_num = 1,
    .flags = 0,
    .rx_config = {
        .idle_threshold = 12000,  // 12ms空闲阈值(大于这个时间认为是帧结束)
        .filter_ticks_thresh = 100,  // 100 ticks的滤波器(100us)
        .filter_en = true
    },
    .rmt_mode = RMT_MODE_RX //接收模式
};

esp_err_t ir_receiver_init() {
    esp_err_t ret = ESP_OK;

    // 配置RMT接收器
    if ((ret = rmt_config(&rmt_rx_config)) != ESP_OK) {
        ESP_LOGE(TAG, "RMT config failed: %d", ret);
        return ret;
    }

    // 安装RMT驱动
    if ((ret = rmt_driver_install(rmt_rx_config.channel, 1000, 0)) != ESP_OK) {
        ESP_LOGE(TAG, "RMT driver install failed: %d", ret);
        return ret;
    }

    // 获取环形缓冲区句柄
    if ((ret = rmt_get_ringbuf_handle(rmt_rx_config.channel, &rb)) != ESP_OK || rb == NULL) {
        ESP_LOGE(TAG, "RMT get ringbuf handle failed: %d", ret);
        return ESP_FAIL;
    }

    // 创建红外数据队列
    ir_data_queue = xQueueCreate(10, sizeof(ir_nec_data_t));
    if (!ir_data_queue) {
        ESP_LOGE(TAG, "Create IR data queue failed");
        return ESP_FAIL;
    }


    if ((ret = rmt_rx_start(rmt_rx_config.channel, true)) != ESP_OK) {
        ESP_LOGE(TAG, "RMT RX start failed: %d", ret);
        return ret;
    }


     ESP_LOGI(TAG, "IR receiver initialized on GPIO%d", IR_RX_GPIO_NUM);
     return ESP_OK;
}


// NEC协议解码
static bool nec_decode(rmt_item32_t *items, size_t length, ir_nec_data_t *data) {

    // 检查重复码
    if (length == 2)
    {
        if (items[0].duration0 > 9000 && items[0].duration0 < 11000 &&
            items[0].duration1 > 1500 && items[1].duration1 < 3000 &&
            items[1].duration0 > 500 && items[1].duration0 < 800 &&
            items[1].duration1 == 00)
        {
            data->repeat = true;
            return true;
        }
    }
    else if (length == 34)
    {
        // 检查引导码
        if ((items[0].duration0 < 9000 || items[0].duration0 > 11000) &&
            (items[0].duration1 < 3000 || items[0].duration1 > 6000))
        {
            ESP_LOGI(TAG, "items[0] false");
            ESP_LOGI(TAG, "items[0] duration0 = %d duration1 = %d", items[0].duration0, items[0].duration1);
        }

        data->repeat = false;
        data->address = 0;
        data->command = 0;

        // 解码32位数据
        for (int i = 1; i < 33; i++)
        {
            if (items[i].duration0 < 300 || items[i].duration0 > 1800)
            {
                ESP_LOGI(TAG, "items[%d] false", i);
                ESP_LOGI(TAG, "items[%d] duration0 = %d duration1 = %d", i, items[i].duration0, items[i].duration1);
                return false;
            }

            if (items[i].duration1 > 1300 && items[i].duration1 < 1800)
            {
                // 逻辑1
                if (i <= 16)
                {
                    data->address |= (1 << (16 - i));
                }
                else
                {
                    data->command |= (1 << (32 - i));
                }
            }
            else if (items[i].duration1 > 300 && items[i].duration1 < 700)
            {
                // 逻辑0
                // 不需要操作，因为初始值已经是0
            }
            else
            {
                ESP_LOGI(TAG, "items[%d] false", i);
                ESP_LOGI(TAG, "items[%d] duration0 = %d duration1 = %d", i, items[i].duration0, items[i].duration1);
                return false;
            }
        }

        // 检查停止位
        if (items[33].duration0 < 400 || items[33].duration0 > 1000)
        {
            ESP_LOGI(TAG, "items[%d] false", 33);
            ESP_LOGI(TAG, "items[33] duration0 = %d duration1 = %d", items[33].duration0, items[33].duration1);
            return false;
        }

        return true;
    }
   // ESP_LOGI(TAG, "items length= %d", length);
    return false;
}


//红外发送模拟
static const rmt_item32_t morse_esp[] = {
	// E : dot
	{{{ 3270, 1, 3270, 0 }}}, // dot
	{{{ 3270, 0, 3270, 0 }}}, // SPACE
	// S : dot, dot, dot
	{{{ 3270, 1, 3270, 0 }}}, // dot
	{{{ 3270, 1, 3270, 0 }}}, // dot
	{{{ 3270, 1, 3270, 0 }}}, // dot
	{{{ 3270, 0, 3270, 0 }}}, // SPACE
	// P : dot, dash, dash, dot
	{{{ 3270, 1, 3270, 0 }}}, // dot
	{{{ 3270, 1, 3270, 1 }}},
	{{{ 3270, 1, 3270, 0 }}}, // dash
	{{{ 3270, 1, 3270, 1 }}},
	{{{ 3270, 1, 3270, 0 }}}, // dash
	{{{ 3270, 1, 3270, 0 }}}, // dot
	// RMT end marker
	{{{ 0, 1, 0, 0 }}}
};

static void rmt_tx_init(void)
{
	//01 rmt driver共有部分
	rmt_config_t rmt;
	rmt.channel = RMT_CHANNEL_0; //RMT有0-7一共8个通道
	rmt.clk_div = 80;  //默认的时钟是80MHZ，分频器是8位的，这个时钟与发送信号时候电平长度以及接收信号时候计数有关系。 n个时钟周期就是电平长度.如果80分频，数一个数就是1us
	rmt.gpio_num = IR_RX_GPIO_NUM;
	rmt.mem_block_num = 1; //默认每个通道使用1个block。一共block是64x32bit 这么大。 也就是能储存128个数据
	rmt.rmt_mode = RMT_MODE_TX; //配置发送模式


	//02 配置tx独有的部分
	rmt.tx_config.carrier_en = true; //打开载波
	rmt.tx_config.carrier_freq_hz = 38000; //38khz载波
	rmt.tx_config.carrier_duty_percent = 50; //占空比50%
	rmt.tx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH; //载波默认为高电平
	rmt.tx_config.idle_output_en = true; //空闲输出打开
	rmt.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; //空闲时候为低电平
	rmt.tx_config.loop_en = false; //关闭持续发送

	//03 进行配置

	rmt_config(&rmt);
	//04 加载配置
	rmt_driver_install(RMT_CHANNEL_0, 0, 0); //发送不需要缓冲区，中断级别默认
}

void setup() {
	rmt_tx_init();
	while (1)
	{
		rmt_write_items(RMT_CHANNEL_0, morse_esp, sizeof(morse_esp) / sizeof(morse_esp[0]), true);
		vTaskDelay(100 / portTICK_PERIOD_MS);

	}
}



// 读取红外遥控数据
void Rmt_Task(void *args)
{
    ir_nec_data_t data;
    rmt_item32_t *items = NULL;
    size_t length = 0;
    int rep_cont = 0;
    bool rep_flag = 0;
    // 初始化红外接收器
    if (ir_receiver_init() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize IR receiver");
        return;
    }
    
    ESP_LOGI(TAG, "IR receiver ready. Waiting for IR data...");
   // setup();

    while (1)
    {
        items = (rmt_item32_t *)xRingbufferReceive(rb, &length, 1);
        if (items) {
            length /= sizeof(rmt_item32_t);

            if (nec_decode(items, length, &data) && rep_flag == 0) {
                ESP_LOGI(TAG, "IR receiver data.addr = 0x%04x data.command = 0x%04x  data.repet = 0x%04x length = %d" ,data.address, data.command , data.repeat , length);
                switch (data.command)
                {
                case IR_POWER_KEY:
                case IR2_POWER_KEY:
                    Sys_Status.Key_Vaule = Power_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_START_KEY:
                case IR2_START_KEY:
                    Sys_Status.Key_Vaule = Start_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_TIME_ADD_KEY:
                case IR2_TIME_ADD_KEY:
                    Sys_Status.Key_Vaule = Time_Add_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_TIME_SUB_KEY:
                case IR2_TIME_SUB_KEY:
                    Sys_Status.Key_Vaule = Time_Sub_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_HEAT_ADD_KEY:
                case IR2_HEAT_ADD_KEY:
                    Sys_Status.Key_Vaule = Heat_Add_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_HEAT_SUB_KEY:
                case IR2_HEAT_SUB_KEY:
                    Sys_Status.Key_Vaule = Heat_Sub_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_MODE_ADD_KEY: // 按键冲突
                //case IR2_MODE_ADD_KEY:
                    Sys_Status.Key_Vaule = Mode_Add_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_MODE_SUB_KEY:
                case IR2_MODE_SUB_KEY:
                    Sys_Status.Key_Vaule = Mode_Sub_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_STR_ADD_KEY:
                //case IR2_STR_ADD_KEY:
                    Sys_Status.Key_Vaule = Str_Add_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                case IR_STR_SUB_KEY:
                case IR2_STR_SUB_KEY:
                    Sys_Status.Key_Vaule = Str_Sub_Key;
                    rep_flag = 1; rep_cont = 0;
                    xSemaphoreGive(sem_Key_Value);
                    break;
                }
            }
            vRingbufferReturnItem(rb, items);
        }

        if( rep_flag == 1 ) // 防止按键重复触发
        {
            rep_cont ++;
            if(rep_cont > 140)  // 0.14秒内不重复触发
            {
                rep_cont = 0; rep_flag = 0;
            }
        }
        vTaskDelay(1); // 延时1ms
    }
}
